package com.test.tinyurl.domain.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.hash.Hashing;
import com.test.tinyurl.common.ResponseResult;
import com.test.tinyurl.domain.bean.Link;
import com.test.tinyurl.domain.service.LinkService;
import com.test.tinyurl.util.PageLimitUtil;
import com.test.tinyurl.util.ResponseUtil;
import org.hibernate.validator.constraints.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 短连接对外服务接口
 * 方案一、采用hash进行生成短链接
 * 方案二、采用snowflake雪花算法
 * 方案三、依赖数据库，使用如MySQL自增列或Oracle序列等。
 * 方案四、UUID随机数
 */
@Validated
@RestController
@RequestMapping(value = "/links")
public class LinkController {

    /**
     * 注入redisTemplate
     */
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 注入LinkService
     */
    @Autowired
    private LinkService linkService;

    /**
     * 根据传入URL生成短链接并返回对应请求地址
     * !.采用murmur3_32 hash算法将URL转换成hashcode
     * 2.将生成的hashcode与传入的url进行redis存储，
     * 3.组装生成的短链接请求全路径
     * 4.返回生成的短链接全路径
     *
     * @param fullLink
     * @return
     */
    @PostMapping(value = "/fullLink")
    public ResponseResult createShortUrl(@NotBlank @URL @RequestParam("fullLink") String fullLink) throws Exception {

        //采用murmur3_32 hash算法将URL转换成hashcode
        String hashCode = Hashing.murmur3_32().hashString(fullLink, StandardCharsets.UTF_8).toString();
        if (linkService.selectLink(hashCode)) {
            return ResponseResult.failure("地址已存在");
        }

        //保存长链接并返回短链接
        String shortLink = linkService.insertLink(fullLink, hashCode);

        //将生成的hashcode与传入的url进行redis存储，
        //此处可以将timeout作为配置
        long timeout = 60L;
        this.redisTemplate.opsForValue().set(shortLink, fullLink, timeout, TimeUnit.SECONDS);

        return ResponseResult.success("操作成功");
    }

    /**
     * 查询所有短链接
     *
     * @param request
     * @return
     */
    @GetMapping(value = "/select")
    public Map<String, Object> selectLink(HttpServletRequest request) {
        Page<Link> condition = PageLimitUtil.page(request);
        IPage<Link> pageList = linkService.page(condition);
        return ResponseUtil.defaultResponse(pageList.getTotal(), pageList.getRecords(), null);
    }

    /**
     * 删除所有短链接
     *
     * @param linkId
     * @return
     */
    @PostMapping(value = "/delete")
    public ResponseResult deleteLink(@NotBlank @RequestParam(value = "linkId") String linkId) {
        linkService.removeById(linkId);
        return ResponseResult.success("删除成功");
    }
}
